#include <modules\graphics\md2_entity_loader.h>

namespace DelGE
{
	namespace Modules
	{
		namespace Graphics
		{
			AnimatedEntity *MD2EntityLoader::LoadFromFile(string sFilepath)
			{
				AnimatedEntity	*pEntity;
				Model			*pModel;
				Mesh			*pMesh;				
				ModelPose		*pModelPose;

				md2_header_t	header;
				md2_skin_t		*pSkins;
				md2_texCoord_t	*pTextureCoords;
				md2_triangle_t	*pIndexedTriangles;
				md2_frame_t		*pFrames;
				int				*pGLCommands;

				FILE *pFile;

				pFile = fopen(sFilepath.c_str(), "rb");

				if (!pFile) return NULL;

				fread(&header, 1, sizeof(md2_header_t), pFile);

				if ((header.ident != MD2_CHECK) || (header.version != MD2_VERSION))
				{
					fclose(pFile);
					return NULL;
				}

				pSkins			= (struct md2_skin_t *)malloc (sizeof (struct md2_skin_t) * header.num_skins);
				pTextureCoords	= (struct md2_texCoord_t *)malloc (sizeof (struct md2_texCoord_t) * header.num_st);
				pIndexedTriangles		= (struct md2_triangle_t *)malloc (sizeof (struct md2_triangle_t) * header.num_tris);
				pFrames			= (struct md2_frame_t *)malloc (sizeof (struct md2_frame_t) * header.num_frames);
				pGLCommands		= (int *)malloc (sizeof (int) * header.num_glcmds);

				fseek(pFile, header.offset_skins, SEEK_SET);
				fread(pSkins, sizeof(struct md2_skin_t), header.num_skins, pFile);

				fseek(pFile, header.offset_st, SEEK_SET);
				fread(pTextureCoords, sizeof(struct md2_texCoord_t), header.num_st, pFile);

				fseek(pFile, header.offset_tris, SEEK_SET);
				fread(pIndexedTriangles, sizeof(struct md2_triangle_t), header.num_tris, pFile);

				fseek(pFile, header.offset_glcmds, SEEK_SET);
				fread(pGLCommands, sizeof(int), header.num_glcmds, pFile);

				fseek(pFile, header.offset_frames, SEEK_SET);
				for (int iFrameIndex = 0; iFrameIndex < header.num_frames; ++iFrameIndex)
				{
					pFrames[iFrameIndex].verts =  (struct md2_vertex_t *)malloc (sizeof (struct md2_vertex_t) *header.num_vertices);

					fread(pFrames[iFrameIndex].scale, sizeof(vec3_t), 1, pFile);
					fread(pFrames[iFrameIndex].translate, sizeof(vec3_t), 1, pFile);
					fread(pFrames[iFrameIndex].name, sizeof(char), 16, pFile);
					fread(pFrames[iFrameIndex].verts, sizeof(md2_vertex_t), header.num_vertices, pFile);
				}

				fclose(pFile);

				pEntity = new AnimatedEntity();

				pModel = Model::CreateBlank();

				pMesh = pModel->GetMesh();	

				for (int iFrameIndex = 0; iFrameIndex < header.num_frames; iFrameIndex ++)
				{
					if (iFrameIndex == 0)
					{
						int iVertexIndex[3];
						iVertexIndex[0] = iVertexIndex[1] = iVertexIndex[2] = 0;

						for (int iIndexedTriangleIndex = 0; iIndexedTriangleIndex < header.num_tris; ++iIndexedTriangleIndex)
						{
							for (int iVertex = 0; iVertex < 3; ++ iVertex)
							{
								int iMD2Index = pIndexedTriangles[iIndexedTriangleIndex].vertex[iVertex];

								float vertexX = pFrames[0].scale[1] * pFrames[0].verts[iMD2Index].v[1] + pFrames[0].translate[1];
								float vertexY = pFrames[0].scale[2] * pFrames[0].verts[iMD2Index].v[2] + pFrames[0].translate[2];
								float vertexZ = pFrames[0].scale[0] * pFrames[0].verts[iMD2Index].v[0] + pFrames[0].translate[0];

								float vertexU = (float)pTextureCoords[pIndexedTriangles[iIndexedTriangleIndex].st[iVertex]].s / header.skinwidth;
								float vertexV = (float)pTextureCoords[pIndexedTriangles[iIndexedTriangleIndex].st[iVertex]].t / header.skinheight;

								float vertexNX = anorms[pFrames[0].verts[iMD2Index].normalIndex][0];
								float vertexNY = anorms[pFrames[0].verts[iMD2Index].normalIndex][1];
								float vertexNZ = anorms[pFrames[0].verts[iMD2Index].normalIndex][2];

								bool bAddvertex = true;

								iVertexIndex[iVertex] = 0;
								for (int i = 0; i < pMesh->GetVertexCount(); i ++)
								{
									Vertex *pVertex = pMesh->GetVertex(i);
									if ( ((pVertex->position[0] == vertexX) &&
										  (pVertex->position[1] == vertexY) &&
										  (pVertex->position[2] == vertexZ)) &&
										 ((pVertex->textureUV[0] == vertexU) &&
										  (pVertex->textureUV[1] == vertexV)) )
									{
										bAddvertex = false;
										break;
									}
									iVertexIndex[iVertex] ++;
								}

								if (bAddvertex)
									pMesh->AddVertex(vertexX, vertexY, vertexZ, vertexU, vertexV, Color(255, 255, 255, 255), vertexNX, vertexNY, vertexNZ);
							}

							pMesh->AddIndexedTriangle(iVertexIndex[0], iVertexIndex[1], iVertexIndex[2]);
						}

						pMesh->BuildMesh();
						pEntity->AddModel(pModel);
					}

					pEntity->AddPose();
					pModelPose = pEntity->GetPose(iFrameIndex)->GetModelPose(0);

					int iVertexIndex = 0;

					for (int iIndexedTriangleIndex = 0; iIndexedTriangleIndex < header.num_tris; ++iIndexedTriangleIndex)
					{
						for (int iVertex = 0; iVertex < 3; ++iVertex)
						{
							int iMD2Index = pIndexedTriangles[iIndexedTriangleIndex].vertex[iVertex];
							float vertexX = pFrames[iFrameIndex].scale[1] * pFrames[iFrameIndex].verts[iMD2Index].v[1] + pFrames[iFrameIndex].translate[1];
							float vertexY = pFrames[iFrameIndex].scale[2] * pFrames[iFrameIndex].verts[iMD2Index].v[2] + pFrames[iFrameIndex].translate[2];
							float vertexZ = pFrames[iFrameIndex].scale[0] * pFrames[iFrameIndex].verts[iMD2Index].v[0] + pFrames[iFrameIndex].translate[0];

							bool bAddvertex = true;

							iVertexIndex = pMesh->GetIndexedTriangle(iIndexedTriangleIndex)->indices[iVertex];

							pModelPose->SetVertexPosition(iVertexIndex, Vector3(vertexX, vertexY, vertexZ));
	
						}
					}
				}

				free(pSkins);			pSkins = NULL;
				free(pTextureCoords);	pTextureCoords = NULL;
				free(pIndexedTriangles);		pIndexedTriangles = NULL;
				free(pGLCommands);		pGLCommands = NULL;
				
				for (int iFrameIndex = 0; iFrameIndex < header.num_frames; ++iFrameIndex)
					free(pFrames[iFrameIndex].verts);
				free(pFrames);			pFrames = NULL;

				return pEntity;
			}

			MD2EntityLoader::vec3_t MD2EntityLoader::anorms[] = 
			{
				{ -0.525731f,  0.000000f,  0.850651f }, 
				{ -0.442863f,  0.238856f,  0.864188f }, 
				{ -0.295242f,  0.000000f,  0.955423f }, 
				{ -0.309017f,  0.500000f,  0.809017f }, 
				{ -0.162460f,  0.262866f,  0.951056f }, 
				{  0.000000f,  0.000000f,  1.000000f }, 
				{  0.000000f,  0.850651f,  0.525731f }, 
				{ -0.147621f,  0.716567f,  0.681718f }, 
				{  0.147621f,  0.716567f,  0.681718f }, 
				{  0.000000f,  0.525731f,  0.850651f }, 
				{  0.309017f,  0.500000f,  0.809017f }, 
				{  0.525731f,  0.000000f,  0.850651f }, 
				{  0.295242f,  0.000000f,  0.955423f }, 
				{  0.442863f,  0.238856f,  0.864188f }, 
				{  0.162460f,  0.262866f,  0.951056f }, 
				{ -0.681718f,  0.147621f,  0.716567f }, 
				{ -0.809017f,  0.309017f,  0.500000f }, 
				{ -0.587785f,  0.425325f,  0.688191f }, 
				{ -0.850651f,  0.525731f,  0.000000f }, 
				{ -0.864188f,  0.442863f,  0.238856f }, 
				{ -0.716567f,  0.681718f,  0.147621f }, 
				{ -0.688191f,  0.587785f,  0.425325f }, 
				{ -0.500000f,  0.809017f,  0.309017f }, 
				{ -0.238856f,  0.864188f,  0.442863f }, 
				{ -0.425325f,  0.688191f,  0.587785f }, 
				{ -0.716567f,  0.681718f, -0.147621f }, 
				{ -0.500000f,  0.809017f, -0.309017f }, 
				{ -0.525731f,  0.850651f,  0.000000f }, 
				{  0.000000f,  0.850651f, -0.525731f }, 
				{ -0.238856f,  0.864188f, -0.442863f }, 
				{  0.000000f,  0.955423f, -0.295242f }, 
				{ -0.262866f,  0.951056f, -0.162460f }, 
				{  0.000000f,  1.000000f,  0.000000f }, 
				{  0.000000f,  0.955423f,  0.295242f }, 
				{ -0.262866f,  0.951056f,  0.162460f }, 
				{  0.238856f,  0.864188f,  0.442863f }, 
				{  0.262866f,  0.951056f,  0.162460f }, 
				{  0.500000f,  0.809017f,  0.309017f }, 
				{  0.238856f,  0.864188f, -0.442863f }, 
				{  0.262866f,  0.951056f, -0.162460f }, 
				{  0.500000f,  0.809017f, -0.309017f }, 
				{  0.850651f,  0.525731f,  0.000000f }, 
				{  0.716567f,  0.681718f,  0.147621f }, 
				{  0.716567f,  0.681718f, -0.147621f }, 
				{  0.525731f,  0.850651f,  0.000000f }, 
				{  0.425325f,  0.688191f,  0.587785f }, 
				{  0.864188f,  0.442863f,  0.238856f }, 
				{  0.688191f,  0.587785f,  0.425325f }, 
				{  0.809017f,  0.309017f,  0.500000f }, 
				{  0.681718f,  0.147621f,  0.716567f }, 
				{  0.587785f,  0.425325f,  0.688191f }, 
				{  0.955423f,  0.295242f,  0.000000f }, 
				{  1.000000f,  0.000000f,  0.000000f }, 
				{  0.951056f,  0.162460f,  0.262866f }, 
				{  0.850651f, -0.525731f,  0.000000f }, 
				{  0.955423f, -0.295242f,  0.000000f }, 
				{  0.864188f, -0.442863f,  0.238856f }, 
				{  0.951056f, -0.162460f,  0.262866f }, 
				{  0.809017f, -0.309017f,  0.500000f }, 
				{  0.681718f, -0.147621f,  0.716567f }, 
				{  0.850651f,  0.000000f,  0.525731f }, 
				{  0.864188f,  0.442863f, -0.238856f }, 
				{  0.809017f,  0.309017f, -0.500000f }, 
				{  0.951056f,  0.162460f, -0.262866f }, 
				{  0.525731f,  0.000000f, -0.850651f }, 
				{  0.681718f,  0.147621f, -0.716567f }, 
				{  0.681718f, -0.147621f, -0.716567f }, 
				{  0.850651f,  0.000000f, -0.525731f }, 
				{  0.809017f, -0.309017f, -0.500000f }, 
				{  0.864188f, -0.442863f, -0.238856f }, 
				{  0.951056f, -0.162460f, -0.262866f }, 
				{  0.147621f,  0.716567f, -0.681718f }, 
				{  0.309017f,  0.500000f, -0.809017f }, 
				{  0.425325f,  0.688191f, -0.587785f }, 
				{  0.442863f,  0.238856f, -0.864188f }, 
				{  0.587785f,  0.425325f, -0.688191f }, 
				{  0.688191f,  0.587785f, -0.425325f }, 
				{ -0.147621f,  0.716567f, -0.681718f }, 
				{ -0.309017f,  0.500000f, -0.809017f }, 
				{  0.000000f,  0.525731f, -0.850651f }, 
				{ -0.525731f,  0.000000f, -0.850651f }, 
				{ -0.442863f,  0.238856f, -0.864188f }, 
				{ -0.295242f,  0.000000f, -0.955423f }, 
				{ -0.162460f,  0.262866f, -0.951056f }, 
				{  0.000000f,  0.000000f, -1.000000f }, 
				{  0.295242f,  0.000000f, -0.955423f }, 
				{  0.162460f,  0.262866f, -0.951056f }, 
				{ -0.442863f, -0.238856f, -0.864188f }, 
				{ -0.309017f, -0.500000f, -0.809017f }, 
				{ -0.162460f, -0.262866f, -0.951056f }, 
				{  0.000000f, -0.850651f, -0.525731f }, 
				{ -0.147621f, -0.716567f, -0.681718f }, 
				{  0.147621f, -0.716567f, -0.681718f }, 
				{  0.000000f, -0.525731f, -0.850651f }, 
				{  0.309017f, -0.500000f, -0.809017f }, 
				{  0.442863f, -0.238856f, -0.864188f }, 
				{  0.162460f, -0.262866f, -0.951056f }, 
				{  0.238856f, -0.864188f, -0.442863f }, 
				{  0.500000f, -0.809017f, -0.309017f }, 
				{  0.425325f, -0.688191f, -0.587785f }, 
				{  0.716567f, -0.681718f, -0.147621f }, 
				{  0.688191f, -0.587785f, -0.425325f }, 
				{  0.587785f, -0.425325f, -0.688191f }, 
				{  0.000000f, -0.955423f, -0.295242f }, 
				{  0.000000f, -1.000000f,  0.000000f }, 
				{  0.262866f, -0.951056f, -0.162460f }, 
				{  0.000000f, -0.850651f,  0.525731f }, 
				{  0.000000f, -0.955423f,  0.295242f }, 
				{  0.238856f, -0.864188f,  0.442863f }, 
				{  0.262866f, -0.951056f,  0.162460f }, 
				{  0.500000f, -0.809017f,  0.309017f }, 
				{  0.716567f, -0.681718f,  0.147621f }, 
				{  0.525731f, -0.850651f,  0.000000f }, 
				{ -0.238856f, -0.864188f, -0.442863f }, 
				{ -0.500000f, -0.809017f, -0.309017f }, 
				{ -0.262866f, -0.951056f, -0.162460f }, 
				{ -0.850651f, -0.525731f,  0.000000f }, 
				{ -0.716567f, -0.681718f, -0.147621f }, 
				{ -0.716567f, -0.681718f,  0.147621f }, 
				{ -0.525731f, -0.850651f,  0.000000f }, 
				{ -0.500000f, -0.809017f,  0.309017f }, 
				{ -0.238856f, -0.864188f,  0.442863f }, 
				{ -0.262866f, -0.951056f,  0.162460f }, 
				{ -0.864188f, -0.442863f,  0.238856f }, 
				{ -0.809017f, -0.309017f,  0.500000f }, 
				{ -0.688191f, -0.587785f,  0.425325f }, 
				{ -0.681718f, -0.147621f,  0.716567f }, 
				{ -0.442863f, -0.238856f,  0.864188f }, 
				{ -0.587785f, -0.425325f,  0.688191f }, 
				{ -0.309017f, -0.500000f,  0.809017f }, 
				{ -0.147621f, -0.716567f,  0.681718f }, 
				{ -0.425325f, -0.688191f,  0.587785f }, 
				{ -0.162460f, -0.262866f,  0.951056f }, 
				{  0.442863f, -0.238856f,  0.864188f }, 
				{  0.162460f, -0.262866f,  0.951056f }, 
				{  0.309017f, -0.500000f,  0.809017f }, 
				{  0.147621f, -0.716567f,  0.681718f }, 
				{  0.000000f, -0.525731f,  0.850651f }, 
				{  0.425325f, -0.688191f,  0.587785f }, 
				{  0.587785f, -0.425325f,  0.688191f }, 
				{  0.688191f, -0.587785f,  0.425325f }, 
				{ -0.955423f,  0.295242f,  0.000000f }, 
				{ -0.951056f,  0.162460f,  0.262866f }, 
				{ -1.000000f,  0.000000f,  0.000000f }, 
				{ -0.850651f,  0.000000f,  0.525731f }, 
				{ -0.955423f, -0.295242f,  0.000000f }, 
				{ -0.951056f, -0.162460f,  0.262866f }, 
				{ -0.864188f,  0.442863f, -0.238856f }, 
				{ -0.951056f,  0.162460f, -0.262866f }, 
				{ -0.809017f,  0.309017f, -0.500000f }, 
				{ -0.864188f, -0.442863f, -0.238856f }, 
				{ -0.951056f, -0.162460f, -0.262866f }, 
				{ -0.809017f, -0.309017f, -0.500000f }, 
				{ -0.681718f,  0.147621f, -0.716567f }, 
				{ -0.681718f, -0.147621f, -0.716567f }, 
				{ -0.850651f,  0.000000f, -0.525731f }, 
				{ -0.688191f,  0.587785f, -0.425325f }, 
				{ -0.587785f,  0.425325f, -0.688191f }, 
				{ -0.425325f,  0.688191f, -0.587785f }, 
				{ -0.425325f, -0.688191f, -0.587785f }, 
				{ -0.587785f, -0.425325f, -0.688191f }, 
				{ -0.688191f, -0.587785f, -0.425325f }
			};
		}
	}
}